package com.googlecode.connectlet.machine.provider.param;

import java.io.IOException;
import java.net.InetAddress;
import java.security.AlgorithmParametersSpi;
import java.security.spec.AlgorithmParameterSpec;
import java.security.spec.InvalidParameterSpecException;

import com.googlecode.connectlet.machine.provider.MachineKey;
import com.googlecode.connectlet.util.Bytes;

public final class MachineParameters extends AlgorithmParametersSpi {
	private MachineKey key = null;

	@Override
	protected byte[] engineGetEncoded() {
		byte[] addr = key.getIp().getAddress();
		byte[] port = Bytes.fromShort(key.getPort());
		byte[] keyId = Bytes.fromInt(key.getKeyId());
		return Bytes.add(addr, port, keyId);
	}

	@Override
	protected byte[] engineGetEncoded(String format) throws IOException {
		return engineGetEncoded();
	}

	@Override
	protected <T extends AlgorithmParameterSpec> T engineGetParameterSpec(Class<T>
			paramSpec) throws InvalidParameterSpecException {
		if (paramSpec.isAssignableFrom(MachineKey.class)) {
			return paramSpec.cast(key);
		}
		throw new InvalidParameterSpecException("paramSpec must be MachineKey");
	}

	@Override
	protected void engineInit(AlgorithmParameterSpec paramSpec) throws InvalidParameterSpecException {
		if (paramSpec instanceof MachineKey) {
			key = (MachineKey) paramSpec;
		} else {
			throw new InvalidParameterSpecException("MachineKey required");
		}
	}

	@Override
	protected void engineInit(byte[] params) throws IOException {
		InetAddress addr = InetAddress.getByAddress(Bytes.left(params, 4));
		int port = Bytes.toShort(params, 4);
		if (port < 0) {
			port += 65536;
		}
		int keyId = Bytes.toInt(params, 6);
		key = new MachineKey(addr, port, keyId);
	}

	@Override
	protected void engineInit(byte[] params, String format) throws IOException {
		engineInit(params);
	}

	@Override
	protected String engineToString() {
		return key.toString();
	}
}